package com.oazon.moco.lan;

import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.util.CharsetUtil;

import java.util.ArrayList;
import java.util.List;

import android.util.Log;

import com.oazon.common.Logger;
import com.oazon.moco.bean.McServiceMsg;
import com.oazon.moco.lan.core.client.ILanRequest;
import com.oazon.moco.lan.core.client.ILanRequestControl;
import com.oazon.moco.lan.core.client.impl.LanRequest;
import com.oazon.moco.lan.core.client.impl.LanRequestControl;
import com.oazon.moco.lan.core.http.HttpJsonRequest;
import com.oazon.moco.lan.core.http.HttpJsonServer;
import com.oazon.moco.lan.core.http.bean.DeleteBean;
import com.oazon.moco.lan.core.http.bean.FavoriteBean;
import com.oazon.moco.lan.core.http.bean.JsonMessageType;
import com.oazon.moco.lan.core.http.bean.JsonRequest;
import com.oazon.moco.lan.core.http.bean.MediaStateInstance;
import com.oazon.moco.lan.core.http.bean.PositionInfo;
import com.oazon.moco.lan.core.http.bean.RequestClassification;
import com.oazon.moco.lan.core.http.bean.RequestOperation;
import com.oazon.moco.lan.core.http.bean.ResponseUriToQueue;
import com.oazon.moco.lan.core.http.bean.ResponseVolume;
import com.oazon.moco.lan.core.http.bean.Seek;
import com.oazon.moco.lan.core.http.bean.SongInfo;
import com.oazon.moco.lan.core.http.bean.Volume;
import com.oazon.moco.lan.core.http.bean.VolumeInstance;
import com.oazon.moco.lan.core.http.bean.ZoneInfo;
import com.oazon.moco.lan.util.LanServer;
import com.oazon.moco.link.core.LinkEventController;
import com.oazon.moco.link.core.LinkSDK;
import com.oazon.moco.link.lan.ResponceEventListener;
import com.oazon.moco.link.ui.LanEventListener;
import com.oazon.moco.link.ui.PlayEventListener;

@Sharable
public class HttpJsonServerHandler extends
		SimpleChannelInboundHandler<HttpJsonRequest> {

	private LinkSDK linkSDK = LinkSDK.getInstance();
	private static String TAG = "HttpJsonServerHandler";
	private HttpJsonServer server = null;
	private ILanRequestControl control;

	public HttpJsonServerHandler(HttpJsonServer server) {
		super();
		this.server = server;
		Log.d(TAG,
				"linkSDK.registLinkListener(responceEventListener);linkSDK.registLinkListener(playEventListener);");
		LinkSDK linkSDK = LinkSDK.getInstance();
		linkSDK.registLinkListener(responceEventListener);
		linkSDK.registLinkListener(playEventListener);
		linkSDK.registLinkListener(lanEventListener);

		ILanRequest lanRequest = new LanRequest(LinkSDK.getAppContext());
		control = new LanRequestControl(lanRequest);
	}

	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception {
		super.channelActive(ctx);
		server.addClient(ctx);
	}

	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		super.channelInactive(ctx);
		Log.e(TAG, "server channel inactive");
		server.removeClient(ctx);
	} 

	@Override
	protected void channelRead0(final ChannelHandlerContext ctx,
			HttpJsonRequest message) throws Exception {
		Object body = message.getBody();
		try {
			HttpMsgManager.getInstance().doBusiness(body, ctx);
		} catch (Exception e) {
			e.printStackTrace();
			responceError(ctx, 400,"doBusiness::"+ e.toString());
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		Log.e(TAG, "server error: " + cause.getMessage());
	}

	private void responseError(ChannelHandlerContext ctx) {
		responceError(ctx, 400, "The request is bad");
	}

	private void responceError(ChannelHandlerContext ctx, int code,
			String errorMsg) {
		if (errorMsg == null) {
			errorMsg = "The request is bad";
		}
		Logger.e(TAG, errorMsg);
		FullHttpResponse response = new DefaultFullHttpResponse(
				HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST,
				Unpooled.copiedBuffer("{\"error\":" + code + ",\"message\":\""
						+ errorMsg + "\"}" + "\r\n", CharsetUtil.UTF_8));
		ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
	}

	private ResponceEventListener responceEventListener = new ResponceEventListener(
			LinkEventController.lanSource) {

		@Override
		protected void responseZoneInfo(ZoneInfo zoneInfo,
				ChannelHandlerContext ctx) {
			LanServer.responseResult(JsonMessageType.GET_ZONE_INFO.toString(),
					0, zoneInfo, ctx);
		}

		@Override
		protected void responseSongInfo(SongInfo songinfo,
				ChannelHandlerContext ctx) {
			super.responseSongInfo(songinfo, ctx);
			LanServer.responseResult(JsonMessageType.GET_SONG_INFO.toString(),
					0, songinfo, ctx);
		}

		@Override
		protected void responseAllStatus(MediaStateInstance instances,
				ChannelHandlerContext ctx) {
			LanServer.responseResult(JsonMessageType.GET_ALL_STATUS.toString(),
					0, instances, ctx);
		}

		@Override
		protected void responsePositionInfo(PositionInfo positionInfo,
				ChannelHandlerContext ctx) {
			LanServer.responseResult(
					JsonMessageType.GET_POSITION_INFO.toString(), 0,
					positionInfo, ctx);
		}

		@Override
		protected void responsePlayMode(String playmode,
				ChannelHandlerContext ctx) {
			super.responsePlayMode(playmode, ctx);
			LanServer.responseResult(JsonMessageType.GET_PLAY_MODE.toString(),
					0, playmode, ctx);
		}

		@Override
		protected void responseVolume(ResponseVolume volume,
				ChannelHandlerContext ctx) {
			LanServer.responseResult(JsonMessageType.GET_VOLUME.toString(), 0,
					volume, ctx);
		}

		@Override
		protected void responseCategory(String category,
				ChannelHandlerContext ctx) {
			super.responseCategory(category, ctx);
			LanServer.responseResult(JsonMessageType.GET_CATEGORY.toString(),
					0, category, ctx);
		}

		@Override
		protected void responsePlayStatus(String playStatus,
				ChannelHandlerContext ctx) {
			super.responsePlayStatus(playStatus, ctx);
			LanServer.responseResult(
					JsonMessageType.GET_PLAY_STATUS.toString(), 0, playStatus,
					ctx);
		}

	};

	private PlayEventListener playEventListener = new PlayEventListener() {

		@Override
		protected void responseAddUriToQueue(
				ResponseUriToQueue responseUriToQueue,
				ChannelHandlerContext channelContext) {

			Log.d("test", "responseAddUriToQueue");
			if (responseUriToQueue != null) {

				LanServer.responseResult(
						JsonMessageType.ADD_URI_TO_QUEUE.toString(), 0,
						responseUriToQueue, channelContext);
			} else {
				LanServer.responseResult(
						JsonMessageType.ADD_URI_TO_QUEUE.toString(), -1, null,
						channelContext);
			}

		}

		@Override
		protected void setVolume(String uuid, VolumeInstance instance) {

			VolumeInstance volumeInstance = new VolumeInstance();
			List<Volume> volume = new ArrayList<Volume>();

			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.SET_VOLUME.toString());
			if (instance.getVolume().size() > 0) {

				Volume object = new Volume();
				object.setChannel(instance.getVolume().get(0).getChannel());
				object.setVal(instance.getVolume().get(0).getVal() * 100 / 32);

				volume.add(object);
				volumeInstance.setVolume(volume);
			}
			jsonRequest.setData(volumeInstance);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {
			}
		};

		@Override
		protected void setProgress(String uuid, Seek seek) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.SEEK.toString());
			jsonRequest.setData(seek);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {
			}
		}

		@Override
		protected void playMode(String uuid, String playMode) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.PLAY_MODE.toString());
			jsonRequest.setData(playMode);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {
			}
		}

		/*
		 * @Override protected void next(String uuid) { JsonRequest jsonRequest
		 * = new JsonRequest(); jsonRequest.setUuid(uuid);
		 * jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
		 * jsonRequest
		 * .setClassification(RequestClassification.CLASSIFICATION_AUDIO);
		 * jsonRequest.setType(JsonMessageType.NEXT.toString()); try {
		 * control.sendRequset(jsonRequest, null); } catch (NullPointerException
		 * e) { } }
		 */
		/*
		 * @Override protected void previous(String uuid) { JsonRequest
		 * jsonRequest = new JsonRequest(); jsonRequest.setUuid(uuid);
		 * jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
		 * jsonRequest
		 * .setClassification(RequestClassification.CLASSIFICATION_AUDIO);
		 * jsonRequest.setType(JsonMessageType.PREVIOUS.toString()); try {
		 * control.sendRequset(jsonRequest, null); } catch (NullPointerException
		 * e) { } }
		 */

		@Override
		protected void delete(String uuid, DeleteBean deleteOrder,
				ChannelHandlerContext ctx) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.DELETE.toString());
			jsonRequest.setData(deleteOrder);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

		@Override
		protected void favorite(String uuid, FavoriteBean favoriteOrder,
				ChannelHandlerContext ctx) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.FAVORITE.toString());
			jsonRequest.setData(favoriteOrder);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

		@Override
		protected void stop(String uuid) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.STOP.toString());
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

		@Override
		protected void pause(String uuid) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.PAUSE.toString());
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

		@Override
		protected void play(String uuid, int instanceID, int speed) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.PLAY.toString());
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

		@Override
		protected void notifyMediaState(String uuid,
				MediaStateInstance instances) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.MEDIA_STATE.toString());
			jsonRequest.setData(instances);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

	};
	LanEventListener lanEventListener = new LanEventListener(
			LinkEventController.lanSource) {

		@Override
		protected void wifiConnectedChange(boolean wificonnected,
				String wifiName) {
			if (wificonnected) {
				LinkSDK.getInstance().openService(
						LinkEventController.lanSource, LinkSDK.PORT);
			} else {
				LinkSDK.getInstance().closeService(
						LinkEventController.lanSource);
			}
		}

		@Override
		protected void notifyServiceChange(List<McServiceMsg> list, String uuid) {
			JsonRequest jsonRequest = new JsonRequest();
			jsonRequest.setUuid(uuid);
			jsonRequest.setOperation(RequestOperation.OPERATION_NOTIFY);
			jsonRequest
					.setClassification(RequestClassification.CLASSIFICATION_AUDIO);
			jsonRequest.setType(JsonMessageType.LIST_SERVICE.toString());
			jsonRequest.setData(list);
			try {
				control.sendRequset(jsonRequest, null);
			} catch (NullPointerException e) {

			}
		}

	};
}